package com.reliable.service.utils;

import com.reliable.common.utils.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * ID 加解密工具类（纯静态，无需 Spring）
 * 特点：
 * - 使用 AES 加密
 * - 支持格式化输出（可选：普通字符串 或 类 UUID 风格）
 * - 可逆：encrypt → decrypt
 * - 不依赖任何第三方库（仅 JDK）
 */
public class IdEncryptUtils {

    // 🔑 密钥（建议修改为你自己的，至少 16 字符）
    private static final String SECRET_KEY = "xss-mingjianjiami";

    // 📐 是否格式化为类 UUID 风格：a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6
    private static final boolean FORMAT_AS_UUID = false; // 修改为 false

    // 缓存生成的密钥（16 字节）
    private static final byte[] AES_KEY = hashKey(SECRET_KEY);

    /**
     * 加密 Long ID → 字符串（可选格式化为 UUID 风格）
     */
    public static String encrypt(Long id) {
        if (id == null) return null;
        try {
            SecretKeySpec secretKey = new SecretKeySpec(AES_KEY, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] encryptedBytes = cipher.doFinal(id.toString().getBytes(StandardCharsets.UTF_8));
            String encoded = Base64.getUrlEncoder().withoutPadding().encodeToString(encryptedBytes);

            return FORMAT_AS_UUID ? formatAsUuidStyle(encoded) : encoded;
        } catch (Exception e) {
            throw new RuntimeException("ID 加密失败", e);
        }
    }

    /**
     * 加密 Long ID → 字符串（可选格式化为 UUID 风格）
     */
    public static String encrypt(String id) {
        if (StringUtils.isEmpty(id)) return null;
        try {
            SecretKeySpec secretKey = new SecretKeySpec(AES_KEY, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            byte[] encryptedBytes = cipher.doFinal(id.getBytes(StandardCharsets.UTF_8));
            String encoded = Base64.getUrlEncoder().withoutPadding().encodeToString(encryptedBytes);

            return FORMAT_AS_UUID ? formatAsUuidStyle(encoded) : encoded;
        } catch (Exception e) {
            throw new RuntimeException("ID 加密失败", e);
        }
    }

    /**
     * 解密 字符串 → Long ID
     */
    public static Long decrypt(String encryptedId) {
        if (encryptedId == null || encryptedId.trim().isEmpty()) return null;
        try {
            // 去除 UUID 风格的 -
            
            byte[] decoded = Base64.getUrlDecoder().decode(encryptedId);

            SecretKeySpec secretKey = new SecretKeySpec(AES_KEY, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            byte[] decryptedBytes = cipher.doFinal(decoded);
            return Long.parseLong(new String(decryptedBytes, StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("ID 解密失败，请检查输入是否合法", e);
        }
    }
    public static String decryptString(String encryptedId) {
        if (encryptedId == null || encryptedId.trim().isEmpty()) return null;
        try {
            // 去除 UUID 风格的 -

            byte[] decoded = Base64.getUrlDecoder().decode(encryptedId);

            SecretKeySpec secretKey = new SecretKeySpec(AES_KEY, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            byte[] decryptedBytes = cipher.doFinal(decoded);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("ID 解密失败，请检查输入是否合法", e);
        }
    }

    /**
     * 将 Base64 字符串格式化为每6个字符一个"-"的风格
     */
    private static String formatAsUuidStyle(String base64) {
        // 只保留 Base64 合法字符
        return base64.replaceAll("[^a-zA-Z0-9\\-_]", "");
    }

    /**
     * 使用 SHA-256 将字符串密钥哈希为 16 字节 AES 密钥
     */
    private static byte[] hashKey(String key) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(key.getBytes(StandardCharsets.UTF_8));
            byte[] aesKey = new byte[16];
            System.arraycopy(hash, 0, aesKey, 0, 16);
            return aesKey;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密钥生成失败", e);
        }
    }
}
